package Application.Tool;

import Application.AppJoint;
import Application.Controller.ChannelPenSettingsController;
import Application.Mask.MaskManager;
import javafx.scene.Parent;
import javafx.fxml.FXMLLoader;
import Application.LayerImage.LayerImage;
import javafx.scene.input.MouseEvent;
import Application.Layer.Layer;
import Application.Layer.LayerDelegate;

public class ChannelPen extends Tool {
    private Parent root;
    private static ChannelPen ins = new ChannelPen();

    private LayerImage mask;
    private int size;
    private boolean alphaUsed = false;
    private boolean redUsed = true;
    private boolean greenUsed = true;
    private boolean blueUsed = true;
    private int alphaDelta = 0;
    private int redDelta = 10;
    private int greenDelta = 10;
    private int blueDelta = 10;

    private ChannelPen() {
        super();
        // 加载本工具的工具设置
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/ChannelPenSettings.fxml"));
            root = loader.load();

            AppJoint.getInstance().loadMasksToComboBox(
                    ((ChannelPenSettingsController)loader.getController()).getCombo()
            );
        } catch(Exception e) {
            e.printStackTrace();
        }

        mask = MaskManager.getInstance().getMaskByName("test");
    }

    public static ChannelPen getInstance() {
        return ins;
    }




// 属性 ***********************************************************************
    public void setSize(int size) {
        this.size = size;
    }

    public void setMask(String maskName) {
        this.mask = MaskManager.getInstance().getMaskByName(maskName);
    }

    public void setAlpha(boolean used, int delta) {
        this.alphaUsed = used;
        this.alphaDelta = delta;
    }

    public void setRed(boolean used, int delta) {
        this.redUsed = used;
        this.redDelta = delta;
    }

    public void setGreen(boolean used, int delta) {
        this.greenUsed = used;
        this.greenDelta = delta;
    }

    public void setBlue(boolean used, int delta) {
        this.blueUsed = used;
        this.blueDelta = delta;
    }
// ****************************************************************************



// 绘制 ***********************************************************************
    private int[][] cacheA, cacheR, cacheG, cacheB;

    private int blend(int old, int gray, int i, int j) {
        int a0 = (old >> 24) & 0xff;
        int r0 = (old & 0x00ff0000) >> 16;
        int g0 = (old & 0x0000ff00) >> 8;
        int b0 = (old & 0x000000ff);

        int a = a0, r = r0, g = g0, b = b0;
        if(cacheA[i][j] < Math.abs(alphaDelta) && alphaUsed) {
            int grow = alphaDelta * gray / 255;
            a = a0 + grow;
            if(a > 255) {
                a = 255;
            }
            if(a < 0) {
                a = 0;
            }
            cacheA[i][j] += Math.abs(grow);
        }
        if(cacheR[i][j] < Math.abs(redDelta) && redUsed) {
            int grow = redDelta * gray / 255;
            r = r0 + grow;
            if(r > 255) {
                r = 255;
            }
            if(r < 0) {
                r = 0;
            }
            cacheR[i][j] += Math.abs(grow);
        }
        if(cacheG[i][j] < Math.abs(greenDelta) && greenUsed) {
            int grow = greenDelta * gray / 255;
            g = g0 + grow;
            if(g > 255) {
                g = 255;
            }
            if(g < 0) {
                g = 0;
            }
            cacheG[i][j] += Math.abs(grow);
        }
        if(cacheB[i][j] < Math.abs(blueDelta) && blueUsed) {
            int grow = blueDelta * gray / 255;
            b = b0 + grow;
            if(b > 255) {
                b = 255;
            }
            if(b < 0) {
                b = 0;
            }
            cacheB[i][j] += Math.abs(grow);
        }

        return (a << 24) | (r << 16) | (g << 8) | b;
    }

    @Override public void onMouseMove(MouseEvent e) {
        double pixelx =
                e.getX() / AppJoint.getInstance().getImageView().getFitWidth() * AppJoint.getInstance().getCanvasWidth();
        double pixely =
                e.getY() / AppJoint.getInstance().getImageView().getFitHeight() * AppJoint.getInstance().getCanvasHeight();
        Layer activeLayer = LayerDelegate.getInstance().getLayerById(AppJoint.getInstance().getActiveLayerId());

        for(int i = -size / 2; i < size / 2; i++) {
            for(int j = -size / 2; j < size / 2; j++) {
                // 实际像素位置
                int imgx = (int)pixelx + i;
                int imgy = (int)pixely + j;
                if(imgx >= 0 && imgx < AppJoint.getInstance().getCanvasWidth() && imgy >= 0 && imgy < AppJoint.getInstance().getCanvasHeight()) {
                    // 蒙版像素位置
                    int maskx = (i + size / 2) * MaskManager.MASK_SIZE / size;
                    int masky = (j + size / 2) * MaskManager.MASK_SIZE / size;
                    // 蒙版灰度
                    int gray = (mask.getPixelArgb(maskx, masky) & 255);

                    int oldColor = activeLayer.getArgb(imgx, imgy);
                    int newColor = this.blend(oldColor, gray, imgx, imgy);

                    activeLayer.setArgb(imgx, imgy, newColor);
                    LayerDelegate.getInstance().refreshSingle(imgx, imgy);
                }
            }
        }
    }

    @Override public void onMouseDown(MouseEvent e) {
        int width = AppJoint.getInstance().getCanvasWidth();
        int height = AppJoint.getInstance().getCanvasHeight();
        cacheA = new int[width][height];
        cacheR = new int[width][height];
        cacheG = new int[width][height];
        cacheB = new int[width][height];

        onMouseMove(e);
    }

    @Override public void onMouseUp(MouseEvent e) {

    }
// ****************************************************************************




    @Override public Parent getToolSettings() {
        return root;
    }
}
